/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-12-10     xu       the first version
 */
#include "hzk16.h"
#include <fal.h>
#include <rtthread.h>

#define FONT_WIDTH 16
#define FONT_HEIGHT 16
#define FONT_BYTES 32

#define SECTION_CHAR_NUM 94

#define SECTION_CODE_BASE 0xA0
#define POSITION_CODE_BASE 0xA0

const hzk16_info_t hzk16_info = {.width = FONT_WIDTH, .height = FONT_HEIGHT, .size = FONT_BYTES};

const hzk16_info_t* hzk16_get_font_info()
{
    return &hzk16_info;
}

const uint32_t hzk16_font_size = FONT_WIDTH;

hzk16_data_t hzk16_data_create()
{
    rt_size_t total_size = sizeof(hzk16_data_t) + FONT_BYTES;
    hzk16_data_t data = rt_malloc(total_size);
    if (data == RT_NULL) {
        rt_kprintf("alloc hzk16_data_t failed!\n");
        return RT_NULL;
    }
    rt_memset(data, 0, total_size);
    data->size = FONT_BYTES;
    return data;
}

void hzk16_data_destroy(hzk16_data_t data)
{
    if (data == RT_NULL) {
        return;
    }
    rt_free(data);
}

int hzk16_get_font_data(hzk16_code_t chinese, hzk16_data_t data)
{
    if (chinese.gbk_code[0] <= SECTION_CODE_BASE || chinese.gbk_code[1] <= POSITION_CODE_BASE) {
        return -1;
    }
    if (data == RT_NULL || data->size < FONT_BYTES) {
        return -1;
    }

    uint32_t section_code = chinese.gbk_code[0] - SECTION_CODE_BASE;
    uint32_t position_code = chinese.gbk_code[1] - POSITION_CODE_BASE;
    uint32_t offset = (SECTION_CHAR_NUM * (uint32_t)(section_code - 1) + (position_code - 1)) * FONT_BYTES;
    rt_kprintf("%s: offset = %d, size = %d\n", __func__, offset, data->size);
    if (offset > hzk16_data_size || offset + data->size > hzk16_data_size) {
        rt_kprintf("offset %d out of range\n", offset);
        return -1;
    }

#ifdef APP_BUILD_HZK16_TO_FIRMWARE
    rt_memcpy(data->data, &hzk16_data[offset], data->size);
#else
    fal_partition_t part = (fal_partition_t)fal_partition_find(FONT_PART_NAME);
    if (part == RT_NULL) {
        rt_kprintf("partition %s not found!\n", FONT_PART_NAME);
        return -1;
    }

    int retval = fal_partition_read(part, offset, data->data, data->size);
    if (retval < 0) {
        rt_kprintf("read partition %s at %d failed!\n", FONT_PART_NAME, offset);
        return -1;
    }
#endif
    return 0;
}

static int hzk16_test(int argc, char* argv[])
{
    int retval = 0;

    uint8_t target_code[] = {0x04, 0x80, 0x0E, 0xA0, 0x78, 0x90, 0x08, 0x90, 0x08, 0x84, 0xFF,
                             0xFE, 0x08, 0x80, 0x08, 0x90, 0x0A, 0x90, 0x0C, 0x60, 0x18, 0x40,
                             0x68, 0xA0, 0x09, 0x20, 0x0A, 0x14, 0x28, 0x14, 0x10, 0x0C};

    const hzk16_info_t* info = hzk16_get_font_info();
    if (info == RT_NULL) {
        rt_kprintf("get font info failed!\n");
        return -1;
    }

    hzk16_data_t font_data = hzk16_data_create();
    if (font_data == RT_NULL) {
        rt_kprintf("create hzk16 data failed!");
        return -1;
    }

    hzk16_code_t font_code = {
        .gbk_code = {0xCE, 0xD2},
    };

    rt_kprintf("Try to get font data for %02X%02X:\n", font_code.gbk_code[0], font_code.gbk_code[1]);
    retval = hzk16_get_font_data(font_code, font_data);
    if (retval < 0) {
        rt_kprintf("get font data failed!\n");
        hzk16_data_destroy(font_data);
        return -1;
    }

    rt_kprintf("Font data we got:\n");
    for (int i = 0; i < font_data->size; i++) {
        rt_kprintf("%02X, ", font_data->data[i]);
    }
    rt_kprintf("\n");

    rt_kprintf("Font data expected:\n");
    for (int i = 0; i < sizeof(target_code) / sizeof(target_code[0]); i++) {
        rt_kprintf("%02X, ", target_code[i]);
    }
    rt_kprintf("\n");

    if (rt_memcmp(target_code, font_data->data, font_data->size)) {
        rt_kprintf("Test FAIL, data mismatch!\n");
    }
    hzk16_data_destroy(font_data);
    rt_kprintf("Test OK!\n");
    return 0;
}
MSH_CMD_EXPORT(hzk16_test, hzk16 font data test);
